package api

import (
	"github.com/kataras/iris/context"
	"github.com/kataras/iris/core/errors"
	"github.com/ngaut/log"
	"github.com/shopspring/decimal"
	"global/function"
	"global/structs"
	"server/bitkop/app/common"
	"server/bitkop/app/constants"
	"server/bitkop/core"
	"time"
	"github.com/golibs/uuid"
	"encoding/json"
)

func TrustForm(ctx context.Context) {

	p := structs.TrustInfo{}
	err := ctx.ReadForm(&p)
	if err != nil {
		log.Errorf("read form error, msg: %s", err.Error())
		ctx.JSON(common.Error(constants.PARAMETER_ERROR, err.Error()))
		return
	}

	if pass, err := checkParams(p); !pass {
		log.Errorf("check params error, msg: %s", err.Error())
		ctx.JSON(common.Error(constants.PARAMETER_ERROR, err.Error()))
		return
	}

	// 添加到 redis 即可
	// 需要保存详细 item 数据和 queue
	conn := core.BK.Redis.OTEPool.Get()
	defer conn.Close()

	coinPair := function.CoinPairName(p.CoinFrom, p.CoinTo)
	conn.Send("MULTI")
	// 加入队列
	queueData := trustData(p)
	encodeData, err := function.JsonEncode(queueData)
	if err != nil {
		ctx.JSON(common.Error(constants.REDIS_ERROR, err.Error()))
		log.Errorf("json encode error, msg: %s, p: %v", err.Error(), p)
		conn.Do("DISCARD")
		return
	}

	// 存放到详情列表
	var key string
	var queueType structs.TaskType
	if p.Type == "buy" {
		key = function.GetBuyTrustDetailKey(coinPair)
		queueType = structs.TASK_BUY
	} else {
		key = function.GetSaleTrustDetailKey(coinPair)
		queueType = structs.TASK_SALE
	}
	err = conn.Send("HSET", key, p.TrustId, encodeData)
	if err != nil {
		ctx.JSON(common.Error(constants.REDIS_ERROR, err.Error()))
		log.Errorf("hset error, msg: %s, p: %v", err.Error(), p)
		conn.Do("DISCARD")
		return
	}

	// 存储到用户个人的买卖委托单列表
	userTrustKey := function.GetUserTrustKey(p.Type, coinPair, p.Uid)
	err = conn.Send("HSET", userTrustKey, p.TrustId, encodeData)
	if err != nil {
		ctx.JSON(common.Error(constants.REDIS_ERROR, err.Error()))
		log.Errorf("hset user trust error, msg: %s, p: %v", err.Error(), p)
		conn.Do("DISCARD")
		return
	}

	queue := structs.Queue{
		Uuid: 		uuid.Rand().Hex(),
		Type: 		queueType,
	}

	queueMarshalData, err := json.Marshal(queue)
	if err != nil {
		ctx.JSON(common.Error(constants.REDIS_ERROR, err.Error()))
		conn.Do("DISCARD")
		return
	}

	// 添加到队列
	err = conn.Send("RPUSH", function.GetQueueKey(coinPair), string(queueMarshalData))
	if err != nil {
		ctx.JSON(common.Error(constants.REDIS_ERROR, err.Error()))
		log.Errorf("rpush error, msg: %s, p: %v", err.Error(), p)
		conn.Do("DISCARD")
		return
	}

	// 加入详情
	conn.Do("EXEC")
	ctx.JSON(common.Success(true))
}

func trustData(p structs.TrustInfo) structs.TrustCoin {
	return structs.TrustCoin{
		Id:              p.TrustId,
		Uid:             p.Uid,
		Flag:            p.Type,
		CoinFrom:        p.CoinFrom,
		CoinTo:          p.CoinTo,
		NumberAvailable: p.Number,
		Number:          p.Number,
		NumberDeal:      "0.00000000",
		Price:           p.Price,
		IsNew:           "1",
		Status:          0,
		CreateTime:      int(time.Now().Unix()),
		UpdateTime:      time.Now(),
	}
}

// 买卖委托单校验参数
func checkParams(p structs.TrustInfo) (bool, error) {

	number, _ := decimal.NewFromString(p.Number)
	price, _ := decimal.NewFromString(p.Price)

	if number.Cmp(decimal.Zero) == 0 || number.Cmp(decimal.Zero) == -1 ||
		price.Cmp(decimal.Zero) == 0 || price.Cmp(decimal.Zero) == -1 {
		return false, errors.New("price and number should not be less than zero")
	}

	if p.Uid <= 0 {
		return false, errors.New("username should not be less than zero")
	}

	if p.Type != "buy" && p.Type != "sale" {
		return false, errors.New("error type")
	}

	if p.TrustId <= 0 {
		return false, errors.New("trust id should not be less than zero")
	}

	return true, nil
}
